# 一 前言
从本节开始,我们将开始正式介绍 React 优化环节,React 优化会从渲染、加载、海量数据、细节四个方向入手,详细介绍 React 优化过程中的方法和技巧。本章节将重点谈谈 React 的渲染以及优化手段。
通过本章节的学习,你将收获 React 渲染控制的常规方法以及原理,并且学会性能优化的主要手段。
# 二 再谈 React 渲染
对于 React 渲染,你不要仅仅理解成类组件触发 render 函数,函数组件本身执行,事实上,从调度更新任务到调和 fiber,再到浏览器渲染真实 DOM,每一个环节都是渲染的一部分,至于对于每个环节的性能优化,React 在底层已经处理了大部分优化细节,包括设立任务优先级、异步调度、diff算法、时间分片都是 React 为了提高性能,提升用户体验采取的手段。所以,开发者只需要告诉 React 哪些组件需要更新,哪些组件不需要更新。于是,React 提供了 PureComponent,shouldComponentUpdated,memo 等优化手段。这些手段是什么呢?
# render阶段作用是什么?
首先来思考一个问题,组件在一次更新中,类组件执行 render ,执行函数组件 renderWithHooks ( renderWithHook 内部执行 React 函数组件本身),他们的作用是什么呢? 他们真实渲染了 DOM 了吗?显然不是,真实 DOM 是在 commit 阶段挂载的,之前章节打印过 render 后的内容。
那么render的作用是根据一次更新中产生的新状态值,通过 React.createElement ,替换成新的状态,得到新的 React element 对象,新的 element 对象上,保存了最新状态值。 createElement 会产生一个全新的props。到此 render 函数使命完成了。
接下来,React 会调和由 render 函数产生 chidlren,将子代 element 变成 fiber(这个过程如果存在 alternate,会复用 alternate 进行克隆,如果没有 alternate ,那么将创建一个),将 props 变成 pendingProps ,至此当前组件更新完毕。然后如果 children 是组件,会继续重复上一步,直到全部 fiber 调和完毕。完成 render 阶段。
# 三 React 几种控制 render 方法
React 提供了几种控制 render 的方式。我这里会介绍原理和使用。说到对render 的控制,究其本质,主要有以下两种方式:
- 第一种就是从父组件直接隔断子组件的渲染,经典的就是 memo,缓存 element 对象。
- 第二种就是组件从自身来控制是否 render ,比如:PureComponent ,shouldComponentUpdate 。
# 1 缓存React.element对象
第一种是对 React.element 对象的缓存。这是一种父对子的渲染控制方案,来源于一种情况,父组件 render ,子组件有没有必要跟着父组件一起 render ,如果没有必要,则就需要阻断更新流,如下先举两个小例子🌰:
/* 子组件 */
function Children ({ number }){
console.log('子组件渲染')
return <div>let us learn React! { number } </div>
}
/* 父组件 */
export default class Index extends React.Component{
state={
numberA:0,
numberB:0,
}
render(){
return <div>
<Children number={ this.state.numberA } />
<button onClick={ ()=> this.setState({ numberA:this.state.numberA + 1 }) } >改变numberA -{ this.state.numberA } </button>
<button onClick={ ()=> this.setState({ numberB:this.state.numberB + 1 }) } >改变numberB -{ this.state.numberB }</button>
</div>
}
}
对于子组件 Children ,只有 props 中 numberA 更新才是有用的, numberB 更新带来渲染,Children 根本不需要。但是如果不处理子组件的话,就会出现如下情况。无
